package org.mx.mycrm.service.base.impl;

import java.io.Serializable;
import java.util.LinkedHashMap;

import javax.annotation.Resource;
import javax.persistence.Entity;

import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.mx.mycrm.beans.page.QueryResult;
import org.mx.mycrm.service.base.BaseDAO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional
public abstract class BaseDAOSupport implements BaseDAO {
	@Resource SessionFactory sf;
	
	public void save(Object entity) {
		sf.getCurrentSession().persist(entity);
	}
	
	public <T> void delete(Class<T> entityClass, Object entityid) {
		delete(entityClass, new Object[]{entityid});
	}

	public <T> void delete(Class<T> entityClass, Object[] entityids) {
		for (Object id : entityids) {
			sf.getCurrentSession().delete(sf.getCurrentSession().load(entityClass, (Serializable) id));
		}
	}
	public void update(Object entity) {
		sf.getCurrentSession().merge(entity);
	}
	
	@SuppressWarnings("unchecked")
	@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
	public <T> T find(Class<T> entityClass, Object entityId) {
		return (T) sf.getCurrentSession().get(entityClass, (Serializable) entityId);
	}
	
	@SuppressWarnings("unchecked")
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstindex, int maxresult, String wherejpql,
			Object[] queryParams, LinkedHashMap<String, String> orderby) {
		String entityname = getEntityName(entityClass);
		QueryResult qr = new QueryResult<T>();
		Query query = (Query) sf.getCurrentSession().createQuery("select o from "+entityname+" o "+(wherejpql==null? "": "where "+ wherejpql)+buildOrderby(orderby));
		//Query query = em.createQuery("select o from "+entityname+" o "+(wherejpql==null? "": "where "+ wherejpql)+buildOrderby(orderby));
		if(firstindex!=-1 && maxresult!=-1) query.setFirstResult(firstindex).setMaxResults(maxresult);
		setQueryParams(query, queryParams);
		qr.setResultlist(query.list());
		query = (Query) sf.getCurrentSession().createQuery("select count(o) from "+entityname+" o "+(wherejpql==null? "": "where "+ wherejpql));
		//query = em.createQuery("select count(o) from "+entityname+" o "+(wherejpql==null? "": "where "+ wherejpql));
		setQueryParams(query, queryParams);
		qr.setTotalrecord((Long)query.uniqueResult());
		
		return qr;
	}

	@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstindex, int maxresult, LinkedHashMap<String, String> orderby) {
		return getScrollData(entityClass,firstindex,maxresult,null,null,orderby);
	}
	@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstindex, int maxresult, String wherejpql,
			Object[] queryParams) {
		return getScrollData(entityClass,firstindex,maxresult,wherejpql,queryParams,null);
	}
	@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
	public <T> QueryResult<T> getScrollData(Class<T> entityClass,
			int firstindex, int maxresult) {
		return getScrollData(entityClass,firstindex,maxresult,null,null,null);	
	}
	@Transactional(readOnly=true,propagation=Propagation.NOT_SUPPORTED)
	public <T> QueryResult<T> getScrollData(Class<T> entityClass) {
		return getScrollData(entityClass,-1,-1,null,null,null);
	}
	
	protected <T> String getEntityName(Class<T> entityClass){
		String entityname = entityClass.getSimpleName();
		Entity entity =entityClass.getAnnotation(Entity.class );
		if (entity!=null && "".equals(entity)) {
			entityname = entity.name();
		}
		return entityname;
	}
	protected String buildOrderby(LinkedHashMap<String, String> orderby){
		StringBuffer orderbyql = new StringBuffer("");
		if(orderby!=null && orderby.size()>0){
			orderbyql.append(" order by ");
			for(String key : orderby.keySet()){
				orderbyql.append("o.").append(key).append(" ").append(orderby.get(key)).append(",");
			}
			orderbyql.deleteCharAt(orderbyql.length()-1);
		}
		return orderbyql.toString();
	}
	protected void setQueryParams(Query query, Object[] queryParams){
		if(queryParams!=null && queryParams.length>0){
			for(int i=0; i<queryParams.length; i++){
				query.setParameter(i, queryParams[i]);
			}
		}
	}
}
